package com.sinosoft.cloud.access.crypto;

import com.sinosoft.cloud.access.annotations.AccessCrypto;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ClassPathResource;

import javax.annotation.PostConstruct;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Arrays;

import static com.sinosoft.cloud.access.AccessConfiguration.BASE_PACKAGE;


public abstract class CryptoBean {

    private String accessName;
    private String key;
    private String pubKey;
    private String priKey;
    private CryptoType cryptoType;


    private static final String AES_KEY_FILE = "aes.key";
    private static final String DES_KEY_FILE = "des.key";
    private static final String PUB_KEY_FILE = "pub.key";
    private static final String PRI_KEY_FILE = "pri.key";

    /**
     * 读取全局配置文件的对象，主要用于读取是否启用加解密开关
     */
    @Autowired
    private Environment env;

    public Environment getEnv() {
        return env;
    }

    public void setEnv(Environment env) {
        this.env = env;
    }

    public abstract String encryt(String msg);

    public abstract String decryt(String msg);


    public byte[] getCryptoBody(byte[] msg, int start, int length) {
        return Arrays.copyOfRange(msg, start, length);
    }


    public String getKey() {
        return key;
    }

    public void setKey(String key) {
        this.key = key;
    }

    public String getPubKey() {
        return pubKey;
    }

    public void setPubKey(String pubKey) {
        this.pubKey = pubKey;
    }

    public String getPriKey() {
        return priKey;
    }

    public void setPriKey(String priKey) {
        this.priKey = priKey;
    }

    public CryptoType getCryptoType() {
        return cryptoType;
    }

    public void setCryptoType(CryptoType cryptoType) {
        this.cryptoType = cryptoType;
    }

    public String getAccessName() {
        return accessName;
    }

    public void setAccessName(String accessName) {
        this.accessName = accessName;
    }

    @PostConstruct
    public void init() {
        AccessCrypto accessCrypto = AnnotationUtils.findAnnotation(this.getClass(), AccessCrypto.class);
        setAccessName(accessCrypto.name());
        setCryptoType(accessCrypto.cryptoType());
        initKey();

        CryptoFactory cryptoFactory = CryptoFactory.getInstance();
        cryptoFactory.addCrypto(getAccessName(), this);
    }

    private void initKey() {
        switch (getCryptoType()) {
            case AES:
                getAesKey();
        }
    }

    private void getAesKey() {
        ClassPathResource classPathResource = new ClassPathResource(BASE_PACKAGE + accessName + "/" + AES_KEY_FILE);

        if (!classPathResource.exists()) {
            return;
        }

        InputStreamReader isr = null;
        BufferedReader br = null;
        InputStream stream = null;
        StringBuffer str = new StringBuffer(32);
        try {
            stream = classPathResource.getInputStream();
            isr = new InputStreamReader(stream);
            br = new BufferedReader(isr);
            String data = "";
            while ((data = br.readLine()) != null) {
                str.append(data + "");
            }
            setKey(str.toString());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                isr.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                br.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                stream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

}
